classdef HelperGPSNavigationConfig < comm.internal.ConfigBase
    %HelperGPSNavigationConfig GPS navigation data generation configuration
    %object
    %
    %   Note: This is a helper and its API and/or functionality may change
    %   in subsequent releases.
    %
    %   CFG = HelperGPSNavigationConfig creates a Global Positioning System
    %   (GPS) navigation data generation configuration object. The object
    %   contains the parameters required for generation of GPS navigation
    %   data bits. The parameters are described in detail in Appendix II
    %   and III of IS-GPS-200L [1].
    %
    %   CFG = HelperGPSNavigationConfig(Name,Value) creates a GPS
    %   navigation data object, CFG, with the specified property Name set
    %   to the specified Value. You can specify additional name-value pair
    %   arguments in any order as (Name1,Value1,...,NameN,ValueN).
    %
    %   HelperGPSNavigationConfig properties:
    %
    %   DataType                  - Data type of the navigation data
    %   PRNID                     - Pseudo random noise index of satellite
    %   MessageTypes              - CNAV data message types
    %   FrameIndices              - LNAV data frame indices
    %   Preamble                  - Preamble of the navigation data
    %   TLMMessage                - Telemetry message
    %   HOWTOW                    - Time of week in hand-over word
    %   AntiSpoofFlag             - Anti spoof flag
    %   CodesOnL2                 - Ranging code on L2 band
    %   L2PDataFlag               - Indication of presence of navigation
    %                               data bits with P-code on L2 band
    %   L2CPhasing                - Phase relationship indicator of L2C
    %                               signal
    %   CEIDataSet                - Configuration object of type
    %                               <a href="matlab:help('HelperGPSCEIConfig')">HelperGPSCEIConfig</a>
    %   AgeOfDataOffset           - Age of data offset
    %   NMCTAvailabilityIndicator - NMCT availability indicator
    %   NMCTERD                   - NMCT ERD values
    %   AlmanacFileName           - Alamanc file name which has alamanc
    %                               information in SEM format
    %   Ionosphere                - Structure containing Ionosphere
    %                               informtaion
    %   EarthOrientation          - Structure containing Earth's
    %                               orientation information
    %   UTC                       - Structure containing UTC parameters
    %   DifferentialCorrection    - Structure containing differential
    %                               correction parameters
    %   TimeOffset                - Structure containing the parameters
    %                               related to the time offset of GPS with
    %                               respect to other GNSS systems
    %   TextMessage               - Text message in LNAV data
    %   TextInMessageType36       - Text message in CNAV data message type
    %                               36
    %   TextInMessageType15       - Text message in CNAV data message type
    %                               15
    %   Almanac                   - Read-only property of almanac data
    %
    %   References:
    %    [1] IS-GPS-200L. "NAVSTAR GPS Space Segment/Navigation User
    %        Segment Interfaces." GPS Enterprise Space & Missile Systems
    %        Center (SMC) - LAAFB, May 14, 2020.
    %
    %   See also HelperGPSCEIConfig, HelperGPSNAVDataEncode.

    %   Copyright 2021-2022 The MathWorks, Inc.

    properties
        %DataType Data type of the navigation data
        %  Indicate the datatype as one of "CNAV" | "LNAV". The default is
        %  "CNAV".
        DataType = "CNAV"
        %PRNID Pseudo random noise index of satellite
        %  Indicate the PRN ID of the satellite as an integer value from 1
        %  to 210. The default is 1.
        PRNID = 1
        %MessageTypes CNAV data message types
        %  Indicate the message types that needs to be transmitted in that
        %  order either as a column vector or a matrix with number of rows
        %  equal to 4. Navigation data generation happens by considering
        %  the message types as one column vector in column major form.
        %  This property is valid only when DataType is "CNAV". The default
        %  is chosen such that transmission happenes for 12 minutes and the
        %  default value obey the rules given in Section 30.3.4.1 of
        %  IS-GPS-200L.
        MessageTypes = [10 11 37 30; 10 11 32 33; 10 11 12 37; 10 11 12 30; ...
            10 11 12 33; 10 11 12 37; 10 11 12 30; 10 11 32 33; 10 11 37 37; ...
            10 11 32 30; 10 11 12 33; 10 11 12 37; 10 11 12 30; 10 11 12 33; ...
            10 11 12 37].'
        %FrameIndices LNAV data frame indices
        %  Indicate the frame indices that needs to be transmitted in that
        %  order as a vector. This property is valid only only when
        %  DataType is set to "LNAV. The default is an array of integers
        %  from 1 to 25.
        FrameIndices = 1:25
        %Preamble Preamble of the navigation data
        %  Indicate the preamble that needs to be transmitted in the
        %  navigation data. The default is 139.
        Preamble = 139
        %TLMMessage Telemetry message
        %  Indicate the telemetry message that needs to be transmitted in
        %  the LNAV data. This property is valid only when DataType is set
        %  to "LNAV". The default is 0.
        TLMMessage = 0
        %HOWTOW Time of week in hand-over word
        %  Indicate the MSB 17 bits of the time of week value as an
        %  integer. The default is 1.
        HOWTOW = 1
        %AntiSpoofFlag Anti spoof flag
        %  Indicate the anti spoof flag as a binary value. The default is
        %  0.
        AntiSpoofFlag = 0
        %CodesOnL2 Ranging code on L2 band
        %  Indicate the codes on L2 band as one of "P-code" | "C/A-code".
        %  The default is "P-code".
        CodesOnL2 = "P-code"
        %L2PDataFlag Indication of presence of navigation data bits with
        %P-code on L2 band
        %  Indicate the presence of navigation data bits with P-code on L2
        %  band as a binary value. Value of 1 indicates navigation data Off
        %  on P-code of in-phase component of L2 channel. The default is 0.
        L2PDataFlag = 0
        %L2CPhasing Phase relationship indicator of L2C signal
        %  Indicate the phase relationship on L2C signal as a binary value.
        %  Value of 0 indicates that the L2C signal is on phase quadrature.
        %  A value of 1 indicates that L2C signal is in-phase. The default
        %  is 0.
        L2CPhasing = 0
        %CEIDataSet Configuration object of type <a href="matlab:help('HelperGPSCEIConfig')">HelperGPSCEIConfig</a>
        %  Indicate the clock, ephemeris, integrity (CEI) data as a
        %  configuration object of type HelperGPSCEIConfig.
        CEIDataSet = HelperGPSCEIConfig
        %AgeOfDataOffset Age of data offset
        %  Indicate the age of data in seconds. The default is 0.
        AgeOfDataOffset = 0 % In seconds
        %NMCTAvailabilityIndicator NMCT availability indicator
        %  Indicate the presence of NMCT as a binary value. The default is
        %  0.
        NMCTAvailabilityIndicator = 0
        %NMCTERD NMCT ERD values
        %  Indicate the NMCT estimated rate deviation (ERD) values as an
        %  array of 30 elements. The default is a column vector of 30
        %  zeros.
        NMCTERD = zeros(30,1)
        %AlmanacFileName  Alamanc file name which has alamanc information
        %in SEM format
        %  Indicate the alamanc file name as a string scalar or a character
        %  vector. The default is "gpsAlmanac.txt".
        AlmanacFileName = "gpsAlmanac.txt"
        %Ionosphere Structure containing Ionosphere informtaion
        %  Indicate the ionospheric parameters as a structure with fields
        %  "Alpha" and "Beta". The default of each field of the structure
        %  is a column vector of 4 zeros.
        Ionosphere = struct('Alpha',zeros(4,1),'Beta',zeros(4,1))
        %EarthOrientation Structure containing Earth's orientation
        %information
        %  Indicate the Earth orientation parameters as structure with
        %  fields "ReferenceTimeEOP", "XAxisPolarMotionValue",
        %  "XAxisPolarMotionDrift", "YAxisPolarMotionValue",
        %  "YAxisPolarMotionDrift", "UT1_UTCDifference",
        %  "RateOfUT1_UTCDifference". THe default value of each of these
        %  properties is 0.
        EarthOrientation = struct('ReferenceTimeEOP',0,'XAxisPolarMotionValue',0,...
            'XAxisPolarMotionDrift',0,'YAxisPolarMotionValue',0, ...
            'YAxisPolarMotionDrift',0,'UT1_UTCDifference',0, ...
            'RateOfUT1_UTCDifference',0);
        %UTC Structure containing UTC parameters
        %  Indicate the parameters of coordinated universal time (UTC) as a
        %  structure with fields "UTCTimeCoefficients",
        %  "PastLeapSecondCount", "ReferenceTimeUTCData",
        %  "TimeDataReferenceWeekNumber", "LeapSecondReferenceWeekNumber",
        %  "LeapSecondReferenceDayNumber", "FutureLeapSecondCount".
        UTC = struct('UTCTimeCoefficients',[0 0 0],'PastLeapSecondCount',18, ...
            'ReferenceTimeUTCData',0,'TimeDataReferenceWeekNumber', 2149, ...
            'LeapSecondReferenceWeekNumber',2149,'LeapSecondReferenceDayNumber',1, ...
            'FutureLeapSecondCount',18)
        %DifferentialCorrection Structure containing differential
        %correction parameters
        %  Indicate the differential correction parameters as a structure
        %  with fields "ReferenceTimeDCDataPredict", "ReferenceTimeDCData",
        %  "Data". The filed "Data" is an array of structure with fields
        %  "DCDataType", "PRNID", "SVClockBiasCoefficient",
        %  "SVClockDriftCorrection", "UDRAID", "AlphaCorrection",
        %  "BetaCorrection", "GammaCorrection", "InclinationCorrection",
        %  "RightAscensionCorrection", "SemiMajorAxisCorrection",
        %  "UDRARateID".
        DifferentialCorrection = struct('ReferenceTimeDCDataPredict',0, ...
            'ReferenceTimeDCData',0, ...
            'Data',repmat(struct('DCDataType',0,'PRNID',1,'SVClockBiasCoefficient',0, ...
            'SVClockDriftCorrection',0, 'UDRAID',1, ...
            'AlphaCorrection',0,'BetaCorrection',0,'GammaCorrection',0, ...
            'InclinationCorrection',0,'RightAscensionCorrection',0, ...
            'SemiMajorAxisCorrection',0,'UDRARateID',0),31,1))
        %TimeOffset Structure containing the parameters related to the time
        %offset of GPS with respect to other GNSS systems
        %  Indicate the time offset of GPS constellation with respect to
        %  other GNSS constellation as a structure with fields
        %  "ReferenceTimeGGTO", "WeekNumberGGTO", "GNSSID",
        %  "GGTOCoefficients".
        TimeOffset = struct('ReferenceTimeGGTO',0,'WeekNumberGGTO',101, ...
            'GNSSID',0,'GGTOCoefficients',[0;0;0])
        %TextMessage Text message in LNAV data
        %  Indicate the text message that needs to be transmitted on the
        %  LNAV data. It is of length 22 characters. If more characters is
        %  specified, then the text is snipped to 22 characters. If less
        %  than 22 characters is specified, then the additional characters
        %  are filled with blank spaces. The default is 'This content is
        %  part of Satellite Communications Toolbox'.
        TextMessage = 'This content is part of Satellite Communications Toolbox'
        %TextInMessageType36 Text message in CNAV data message type 36
        %  Indicate the text message that needs to be transmitted on the
        %  CNAV data. It is of length 18 characters. If more characters is
        %  specified, then the text is snipped to 18 characters. If less
        %  than 18 characters is specified, then the additional characters
        %  are filled with blank spaces. The default is 'This content is
        %  part of Satellite Communications Toolbox'.
        TextInMessageType36 = 'This content is part of Satellite Communications Toolbox'
        %TextInMessageType15 Text message in CNAV data message type 15
        %  Indicate the text message that needs to be transmitted on the
        %  CNAV data. It is of length 29 characters. If more characters is
        %  specified, then the text is snipped to 29 characters. If less
        %  than 29 characters is specified, then the additional characters
        %  are filled with blank spaces. The default is 'This content is
        %  part of Satellite Communications Toolbox'.
        TextInMessageType15 = 'This content is part of Satellite Communications Toolbox'
    end

    properties(Hidden)
        PageID % Useful while generating the GPS data frame with LNAV data
        SubframeID % Useful while generating LNAV data
        Almanac = struct('SatellitesPRNIndices',1:31, ...
            'WeekNumModulo1024',101, ...
            'ReferenceTimeOfAlmanac',0, ...
            'Data',repmat(struct('PRNID',1, ...
            'SVID',63, ...
            'URAID', 0, ...
            'Eccentricity',0.02, ...
            'InclinationDifference',0, ...
            'RateOfRightAscension',0, ...
            'RootOfSemiMajorAxis',5e3, ...
            'LongitudeOfAscendingNode',0, ...
            'ArgumentOfPerigee',0, ...
            'MeanAnomaly',0, ...
            'SVClockCorrectionCoefficients',[0 0], ...
            'SVHealth',0, ...
            'SVConfig',0, ...
            'L1Health',0, ...
            'L2Health',0, ...
            'L5Health',0),31,1))
    end

    properties(Constant,Hidden)
        DataType_Values = {'CNAV','LNAV'}
        CodesOnL2_Values = {'P-code','C/A-code','invalid'}
    end

    methods
        function obj = HelperGPSNavigationConfig(varargin)
            %HelperGPSNavigationParameters Construct an instance of this class
            %   Support name-value pair arguments when constructing object.
            obj@comm.internal.ConfigBase(varargin{:});
        end

        function al = get.Almanac(obj)
            al = HelperGPSAlmanac2Struct(obj.AlmanacFileName);
            for idx = 1:length(al.Data)
                al.Data(idx).L1Health = obj.Almanac.Data(idx).L1Health;
                al.Data(idx).L2Health = obj.Almanac.Data(idx).L2Health;
                al.Data(idx).L5Health = obj.Almanac.Data(idx).L5Health;
            end
        end

        function cei = get.CEIDataSet(obj)
            cei = obj.CEIDataSet;
            cei.DataType = obj.DataType; % To make sure that DataType property in this file gets carried over to CEI config file
        end

        % Set methods for independent properties validation
        function obj = set.DataType(obj,val)
            prop = 'DataType';
            val = validateEnumProperties(obj, prop, val);
            obj.(prop) = string(val);
        end

        function obj = set.PRNID(obj,val)
            prop = 'PRNID';
            validateattributes(val,{'double','single','uint8'},{'positive','integer','vector','>=',1,'<=',210},mfilename,prop)
            obj.(prop) = val;
        end

        function obj = set.MessageTypes(obj,val)
            prop = 'MessageTypes';
            validateattributes(val,{'double','single','uint8'},{'positive','integer'})
            if ~any(any(ismember(val,[10;11;30;31;32;33;34;35;36;37;12;13;14;15])))
                error('All elements in the MessageTypes property must be from the set {10,11,12,13,14,15,30,31,32,33,34,35,36,37}.')
            end
            obj.(prop) = val;
        end

        function obj = set.FrameIndices(obj,val)
            prop = 'FrameIndices';
            validateattributes(val,{'double','single','uint8'},{'positive','integer','<=',25},mfilename,prop)
            obj.(prop) = val;
        end

        function obj = set.Preamble(obj,val)
            prop = 'Preamble';
            validateattributes(val,{'double','single','uint8'},{'nonnegative','integer'},mfilename,prop)
            obj.(prop) = val;
        end

        function obj = set.TLMMessage(obj,val)
            prop = 'TLMMessage';
            validateattributes(val,{'double','single','uint16'},{'nonnegative','integer'},mfilename,prop)
            obj.(prop) = val;
        end

        function obj = set.HOWTOW(obj,val)
            prop = 'HOWTOW';
            validateattributes(val,{'double','single','uint32'},{'nonnegative','integer'})
            obj.(prop) = val;
        end

        function obj = set.AntiSpoofFlag(obj,val)
            prop = 'AntiSpoofFlag';
            validateattributes(val,{'double','logical'},{'binary'})
            obj.(prop) = val;
        end

        function obj = set.CodesOnL2(obj,val)
            prop = 'CodesOnL2';
            val = validateEnumProperties(obj, prop, val);
            obj.(prop) = val;
        end

        function obj = set.L2PDataFlag(obj,val)
            prop = 'L2PDataFlag';
            validateattributes(val,{'double','logical'},{'binary'},mfilename,prop)
            obj.(prop) = val;
        end

        function obj = set.L2CPhasing(obj,val)
            prop = 'L2CPhasing';
            validateattributes(val,{'double','logical'},{'binary'},mfilename,prop)
            obj.(prop) = val;
        end

        function obj = set.AgeOfDataOffset(obj,val)
            prop = 'AgeOfDataOffset';
            validateattributes(val,{'double','single'},{'nonnegative','<=',27900},mfilename,prop)
            obj.(prop) = val;
        end

        function obj = set.NMCTAvailabilityIndicator(obj,val)
            prop = 'NMCTAvailabilityIndicator';
            validateattributes(val,{'double','logical'},{'binary'},mfilename,prop)
            obj.(prop) = val;
        end

        function obj = set.NMCTERD(obj,val)
            prop = 'NMCTERD';
            validateattributes(val,{'double','single','uint32'},{'vector','numel',30},mfilename,prop)
            obj.(prop) = val;
        end

        function obj = set.AlmanacFileName(obj,val)
            prop = 'AlmanacFileName';
            validateattributes(val,{'char','string'},{},mfilename,prop)
            obj.(prop) = val;
        end

        function obj = set.Ionosphere(obj,val)
            prop = 'Ionosphere';
            validateattributes(val,{'struct'},{},mfilename,prop)
            validateattributes(val.Alpha,{'double','single'},{'vector','numel',4},mfilename,[prop '.Alpha'])
            validateattributes(val.Beta,{'double','single'},{'vector','numel',4},mfilename,[prop '.Beta'])
            obj.(prop) = val;
        end

        function obj = set.EarthOrientation(obj,val)
            prop = 'EarthOrientation';
            validateattributes(val,{'struct'},{},mfilename,prop)
            validateattributes(val.ReferenceTimeEOP,{'double','single'},{'nonnegative','scalar','<=',604784},mfilename,[prop '.ReferenceTimeEOP'])
            validateattributes(val.XAxisPolarMotionValue,{'double','single'},{},mfilename,[prop '.XAxisPolarMotionValue'])
            validateattributes(val.XAxisPolarMotionDrift,{'double','single'},{},mfilename,[prop '.XAxisPolarMotionDrift'])
            validateattributes(val.YAxisPolarMotionValue,{'double','single'},{},mfilename,[prop '.YAxisPolarMotionValue'])
            validateattributes(val.YAxisPolarMotionDrift,{'double','single'},{},mfilename,[prop '.YAxisPolarMotionDrift'])
            validateattributes(val.UT1_UTCDifference,{'double','single'},{},mfilename,[prop '.UT1_UTCDifference'])
            validateattributes(val.RateOfUT1_UTCDifference,{'double','single'},{},mfilename,[prop '.RateOfUT1_UTCDifference'])
            obj.(prop) = val;
        end

        function obj = set.UTC(obj,val)
            prop = 'UTC';
            validateattributes(val,{'struct'},{},mfilename,prop)
            validateattributes(val.UTCTimeCoefficients,{'double','single'},{'vector'},mfilename,[prop '.UTCTimeCoefficients'])
            validateattributes(val.PastLeapSecondCount,{'double','single'},{},mfilename,[prop '.PastLeapSecondCount'])
            validateattributes(val.ReferenceTimeUTCData,{'double','single'},{},mfilename,[prop '.ReferenceTimeUTCData'])
            validateattributes(val.TimeDataReferenceWeekNumber,{'double','single'},{},mfilename,[prop '.TimeDataReferenceWeekNumber'])
            validateattributes(val.LeapSecondReferenceWeekNumber,{'double','single'},{},mfilename,[prop '.LeapSecondReferenceWeekNumber'])
            validateattributes(val.FutureLeapSecondCount,{'double','single'},{},mfilename,[prop '.FutureLeapSecondCount'])
            obj.(prop) = val;
        end

        function obj = set.DifferentialCorrection(obj,val)
            prop = 'DifferentialCorrection';
            validateattributes(val,{'struct'},{},mfilename,prop)
            validateattributes(val.Data,{'struct'},{},mfilename,prop)
            validateattributes(val.ReferenceTimeDCDataPredict,{'double','single'},{'nonnegative','scalar','<=',604500},mfilename,[prop '.ReferenceTimeDCDataPredict'])
            validateattributes(val.ReferenceTimeDCData,{'double','single'},{'nonnegative','scalar','<=',604500},mfilename,[prop '.ReferenceTimeDCData'])
            obj.(prop) = val;
        end

        function obj = set.TimeOffset(obj,val)
            prop = 'TimeOffset';
            validateattributes(val,{'struct'},{},mfilename,prop)
            validateattributes(val.ReferenceTimeGGTO,{'double','single'},{'nonnegative','scalar','<=',604784},mfilename,[prop '.ReferenceTimeGGTO'])
            validateattributes(val.WeekNumberGGTO,{'double','single','uint16'},{'nonnegative','scalar'},mfilename,[prop '.WeekNumberGGTO'])
            validateattributes(val.GNSSID,{'double','single','uint8'},{'nonnegative','scalar','<=',7},mfilename,[prop '.GNSSID'])
            validateattributes(val.GGTOCoefficients,{'double','single'},{'vector','numel',3},mfilename,[prop '.GGTOCoefficients'])
            obj.(prop) = val;
        end

        function obj = set.TextMessage(obj,val)
            prop = 'TextMessage';
            validateattributes(val,{'char','string'},{},mfilename,prop)
            obj.(prop) = val;
        end

        function obj = set.TextInMessageType36(obj,val)
            prop = 'TextInMessageType36';
            validateattributes(val,{'char','string'},{},mfilename,prop)
            obj.(prop) = val;
        end

        function obj = set.TextInMessageType15(obj,val)
            prop = 'TextInMessageType15';
            validateattributes(val,{'char','string'},{},mfilename,prop)
            obj.(prop) = val;
        end
    end

    methods(Access = protected)
        function flag = isInactiveProperty(obj,prop)
            flag = false;
            if any(strcmp(prop,{'MessageTypes','EarthOrientation','DifferentialCorrection','TimeOffset','L2CPhasing','TextInMessageType36','TextInMessageType15'}))
                flag = ~strcmp(obj.DataType,'CNAV');
            elseif any(strcmp(prop,{'NMCTERD','TLMMessage','URAID','FrameIndices','AntiSpoofFlag','CodesOnL2','L2PDataFlag','NMCTAvailabilityIndicator','TextMessage'}))
                flag = ~strcmp(obj.DataType,'LNAV');
            end
        end
    end
end